﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Unity;
using Microsoft.Windows.Controls;
using Might.Infrastructure.DOM;
using Might.Infrastructure.Events;
using Might.Infrastructure.ModelicaDOM;
using Might.Infrastructure.Services;

namespace Might.UIControls.PackageBrowser {
    public class PackageBrowserPresenter {
        private IPackageBrowserView view;
        private readonly IDom domRoot;

        private readonly Dictionary<IDomNode, TreeViewItem> domNodeToTreeViewItemsMapping =
            new Dictionary<IDomNode, TreeViewItem>();

        public PackageBrowserPresenter() {            
            domRoot = CoreServices.Container.Resolve<IDom>();
        }

        public IPackageBrowserView View {
            get { return view; }
            set {
                view = value;
                view.ModelTreeDoubleClick += view_ModelTreeDoubleClick;


                IDomNodeCollection rootModelicaClasses = domRoot.GetChildren(GroupNames.ModelicaClasses);
                rootModelicaClasses.CollectionChanged += DomRootModelicaClass_CollectionChanged;

                foreach (var node in rootModelicaClasses) {
                    addRootToView(node);
                }
            }
        }

        private void addRootToView(IDomNode rootNode) {
            if ((rootNode as IModelicaClass).RestrictedType == ModelicaClassType.Predefined) {
                return;
            }

            TreeViewItem root = new TreeViewItem() {
                Tag = rootNode,
                Header = (rootNode as IModelicaClass).ClassName
            };
            view.AddTreeRoot(root);
            domNodeToTreeViewItemsMapping.Add(rootNode, root);

            IDomNodeCollection children = rootNode.GetChildren(GroupNames.ModelicaClasses);
            foreach (var childNode in children) {
                addItemsToView(childNode);
            }

            children.CollectionChanged += DomNodeModelicaClass_CollectionChanged;

            rootNode.GetChildren(GroupNames.Annotations).CollectionChanged += Anotations_CollectionChanged;
        }

        private void addItemsToView(IDomNode node) {
            TreeViewItem treeItem = new TreeViewItem() {
                Tag = node,
                Header = (node as IModelicaClass).ClassName
            };
            view.AddTreeItem(treeItem, domNodeToTreeViewItemsMapping[node.Parent]);
            domNodeToTreeViewItemsMapping.Add(node, treeItem);

            node.GetChildren(GroupNames.Annotations).CollectionChanged += Anotations_CollectionChanged;

            IDomNodeCollection children = node.GetChildren(GroupNames.ModelicaClasses);
            children.CollectionChanged += DomNodeModelicaClass_CollectionChanged;
            foreach (var childNode in children) {
                addItemsToView(childNode);
            }
        }

        private void DomRootModelicaClass_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            if (e.Action == NotifyCollectionChangedAction.Add) {
                foreach (IDomNode node in e.NewItems) {
                    addRootToView(node);
                }
            } else {
                throw new NotImplementedException();
            }
        }

        private void DomNodeModelicaClass_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            if (e.Action == NotifyCollectionChangedAction.Add) {
                foreach (IDomNode node in e.NewItems) {
                    addItemsToView(node);
                }
            } else {
                throw new NotImplementedException();
            }
        }

        private void Anotations_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            if (e.Action == NotifyCollectionChangedAction.Add) {
                foreach (IDomNode node in e.NewItems) {
                    IDomNodeCollection col = node.GetChildren(GroupNames.Icons);
                    node.GetChildren(GroupNames.Icons).CollectionChanged += Icon_CollectionChanged;
                    if (col.Count > 0) {
                        view.UpdateIcon(domNodeToTreeViewItemsMapping[node.Parent]);
                    }
                }
            } else {
                throw new NotImplementedException();
            }
        }

        private void Icon_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            if (e.Action == NotifyCollectionChangedAction.Add) {
                if (e.NewItems.Count > 0) {
                    view.UpdateIcon(domNodeToTreeViewItemsMapping[(e.NewItems[0] as IDomNode).Parent.Parent]);
                }
            } else {
                throw new NotImplementedException();
            }
        }

        private void view_ModelTreeDoubleClick(object sender, EventArgs e) {
            if (view.SelectedItemData is IDomNode) {
                CoreServices.EventAggregator.GetEvent<PackageBrowserItemOpenEvent>().Publish( view.SelectedItemData as IDomNode );
            }
        }
    }
}
